﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using TfsCommitMonitor.Tfs;

namespace TfsCommitMonitor
{
	internal partial class MainForm : Form
	{
		internal MainForm()
		{
			InitializeComponent();			
			LoadProjects();
			tfsListView1.SelectedIndexChanged += (sender, e) => ChangesetSelectionChanged();
		}

		private void MainForm_Load(object sender, EventArgs e)
		{
			DisplayProjects();
		}

		#region Projects
		private List<Project> _projects;

		private void LoadProjects()
		{
			_projects =
				(ProjectStore.HasPersistedData()
				?
				ProjectStore.LoadFromDisk()
				:
				null)
				??
				new List<Project>();

			AddEventHandlerToProjects();
		}

		private void AddEventHandlerToProjects()
		{
			foreach (var project in _projects)
			{
				project.ChangesetsChanged -= _changesetCollection_ChangesetsChanged;
				project.ChangesetsChanged += _changesetCollection_ChangesetsChanged;
			}
		}

		private void DisplayProjects()
		{
			var nodesToAdd =
				_projects
				.GroupBy(project => project.CollectionUri)
				.OrderBy(
					projectGroup =>
						projectGroup.Select(project => project.ProjectPath.Count(c => c == '/')))
				.ThenBy(
					projectGroup =>
						projectGroup.Select(project => project.ProjectPath))
				.Select(
					projectGroup =>
						new
						{
							Text = projectGroup.Key.AbsoluteUri,
							Nodes = 
								projectGroup
								.Select(project => treeView1.CreateNode(project)),										
						});
							
			treeView1.BeginUpdate();
			try
			{
				treeView1.Nodes.Clear();

				foreach (var node in nodesToAdd)
				{
					var newNode = new TreeNode(node.Text);
					newNode.Nodes.AddRange(node.Nodes.ToArray());
					treeView1.Nodes.Add(newNode);
				}
			}
			finally
			{
				treeView1.EndUpdate();
			}
			treeView1.ExpandAll();
		}

		#endregion

		private void checkNowToolStripMenuItem_Click(object sender, EventArgs e)
		{
			CheckForChanges();
		}

		#region Check For Changes
		private void CheckForChanges()
		{
			foreach (var project in _projects)
			{
				if (!project.PollForChanges())
					DisplayError(project.Error);
			}
			_projects.PersistToDisk();
		}

		private void DisplayError(String error)
		{
			throw new NotImplementedException();
		}

		private void _changesetCollection_ChangesetsChanged(object sender, EventArgs e)
		{
			var project = sender as Project;
			if (project != null)
				ChangesetsChanged(project);
		}

		private void ChangesetsChanged(Project project)
		{
			treeView1.UpdateNode(project);
			if (treeView1.SelectedProject == project)
				DisplayChangesets(project);
		}

		#endregion

		private void addProjectToolStripMenuItem_Click(object sender, EventArgs e)
		{
			AddProject();
		}

		#region Add/Edit
		private void AddProject()
		{
			using (var dialog = new AddEditProjectDialog())
			{
				if (dialog.ShowDialog() == DialogResult.OK)
				{
					_projects.Add(dialog.Project);
					AddEventHandlerToProjects();
					DisplayProjects();
				}
			}
			_projects.PersistToDisk();
		}
		#endregion

		private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
		{
			var project = e.Node.Tag as Project;
			if (project == null)
				ClearChangesets();
			else
				DisplayChangesets(project);
		}
		
		#region Display Changesets
		private void DisplayChangesets(Project project)
		{
			tfsListView1.DisplayChangsets(project.Changesets);
		}

		private void ClearChangesets()
		{
			tfsListView1.Items.Clear();
		}
		#endregion

		#region Display Changes
		private void ChangesetSelectionChanged()
		{
			textBox1.SuspendLayout();
			try
			{
				textBox1.Text = String.Empty;

				if (tfsListView1.SelectedItems.Count > 0)
				{
					var selectedChangesets =
						tfsListView1.SelectedItems
							.Cast<ListViewItem>()
							.Select(item => item.Tag as Changeset)
							.ToArray();

					selectedChangesets.MarkAsRead();

					foreach (ListViewItem item in tfsListView1.SelectedItems)
						item.Font = new Font(tfsListView1.Font, FontStyle.Regular);

					textBox1.Text =
						String.Join(
							ChangeSeperator,
							selectedChangesets
								.Select(GetChangesetChangesText)
								.ToArray());

					treeView1.UpdateNode(treeView1.SelectedProject);
				}
			}
			finally
			{
				textBox1.ResumeLayout();
			}
		}

		private static readonly String ChangeSeperator =
			Environment.NewLine +
			new String('=', 60) +
			Environment.NewLine;

		private static readonly String ChangeFormat = 
			"{0}" + 
			Environment.NewLine + Environment.NewLine +
			new String('-', 30) + Environment.NewLine + 
			"{1}" + 
			Environment.NewLine;

		private static String GetChangesetChangesText(Changeset changeset)
		{
			return
				String.Format(
					ChangeFormat,
					changeset.Comment,
					String.Join(Environment.NewLine,							
						changeset.Changes));
		}
		#endregion

		private void showDiffToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (tfsListView1.SelectedItems.Count == 1)
			    ShowDiff(tfsListView1.SelectedItems[0].Tag as Changeset);
		}
		
		#region Show Diff
		private void ShowDiff(Changeset changeset)
		{
			using (var dialog = new ChangeSetDetailDialog(changeset))
					dialog.ShowDialog();
		}
		#endregion

		private void removeProjectToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (treeView1.SelectedProject != null)
				RemoveProject(treeView1.SelectedProject);
		}

		#region Remove Project
		private void RemoveProject(Project project)
		{
			_projects.Remove(project);
			_projects.PersistToDisk();
			treeView1.RemoveNode(project);
			ClearChangesets();
		}
		#endregion

		#region Form Events
		private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			_projects.PersistToDisk();
		}
		#endregion
	}
}
